/*声明式编程 vs 命令式编程
    声明式编程是一种编程范式， 它关注的是你要做什么，而不是如何做。它表达逻辑而不显式地定义步骤。
    这意味着我们需要根据逻辑的计算来声明要显示的组件。它没有描述控制流步骤
    
    声明式编程的编写方式描述了应该做什么， 而命令式编程描述了如何做。在声明式编程中，让编译器决定如何做事情。
    声明性程序很容易推理，因为代码本身描述了它在做什么。

    const numbers = [1,2,3,4,5];

    // 声明式
    const doubleWithDec = numbers.map(number => number * 2);

    console.log(doubleWithDec)

    // 命令式
    const doubleWithImp = [];
    for(let i=0; i<numbers.length; i++) {
        const numberdouble = numbers[i] * 2;
        doubleWithImp.push(numberdouble)
    }
    console.log(doubleWithImp)
  
    什么是函数式编程
      函数式编程是声明式编程的一部分。javascript中的函数是第一类公民，这意味着函数是数据，
      你可以像保存变量一样在应用程序中保存、检索和传递这些函数
    函数式编程有些核心的概念，如下：

      不可变性(Immutability)
      纯函数(Pure Functions)
      数据转换(Data Transformations)
      高阶函数 (Higher-Order Functions)
      递归
      组合
      
    不可变性意味着不可改变。 在函数式编程中，你无法更改数据，也不能更改。 如果要改变或更改数据，则必须复制数据副本来更改。
    
    在javascript中，函数参数是对实际数据的引用，你不应该使用 student.firstName =“testing11”，这会改变实际的student 对象，
  应该使用Object.assign复制对象并返回新对象。

    纯函数是始终接受一个或多个参数并计算参数并返回数据或函数的函数。
  它没有副作用，例如设置全局状态，更改应用程序状态，它总是将参数视为不可变数据。

  引用传递是指在调用函数时将实际参数的地址传递到函数中，那么在函数中对参数所进行的修改，将影响到实际参数。 
  ECMAScript中所有函数的参数都是按值传递的——《高程3》


  我们可以把ECMAScript函数的参数想象成局部变量。在向参数传递基本类型的值时，被传递的值被复制给一个局部变量（即命名参数，或者用ECMAScript的概念来说，
  就是arguments对象中的一个元素）。在向参数传递引用类型时，会把这个值在内存中的地址（指针）复制给一个局部变量，
  因此这个局部变量的变化会反映在函数的外部。


  setInterval         

  因此setInterval有一些比较致命的问题：

  累积效应，如果setInterval代码在setInterval再次添加到队列之前还没有完成执行，就会导致定时器代码连续运行好几次，而之间没有间隔，就算正常间隔执行，多个setInterval的代码执行时间可能会比预期小（因为代码执行需要一定时间）
  比如你ios的webview，或者safari等浏览器中都有一个特点，在滚动的时候是不执行JS的，如果使用了setInterval，会发现在滚动结束后会执行多次由于滚动不执行JS积攒回调，如果回调执行时间过长，就会非常容易造成卡顿问题和一些不可知的错误（setInterval自带的优化，如果当前事件队列中有setInterval的回调，不会重复添加回调）
  而且把浏览器最小化显示等操作时，setInterval并不是不执行程序，它会把setInterval的回调函数放在队列中，等浏览器窗口再次打开时，一瞬间全部执行

  Web Worker无法访问DOM节点；
Web Worker无法访问全局变量或是全局函数；
Web Worker无法调用alert()或者confirm之类的函数；
Web Worker无法访问window、document之类的浏览器全局变量；

*/
